#include "forward_util.h"
#include "string_util.h"
#include "common.h"
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <string.h>
#include <errno.h>
#include <string>
#include <vector>
using std::string;
using std::vector;

string forward_util::get_sockaddr_str(sockaddr_in& addr){
	static char sz_tmp[32] = {0};
	sprintf(sz_tmp, "%s:%u", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
	return sz_tmp;
}

void forward_util::print_buff(const char * buff, size_t siz){

    char* pCursor = (char*)buff;
    int i = 0;
    unsigned long alloc_siz = siz * 3+1;
    char* show = (char*)malloc(alloc_siz);
    memset(show, 0, alloc_siz);
    for(i = 0; i<siz; ++i){
        char out [3] = {0};
        sprintf(out, "%02x ", pCursor[i]);
        strcat(show, out);
    }

    LOGI("%s", show);
    free(show);
}

sockaddr_in forward_util::get_sockaddr_in(const char* ip, unsigned short port){
	struct sockaddr_in si;
	si.sin_family = PF_INET;
	si.sin_port = htons(port);
	//in_addr in = inet_addr(ip);
	si.sin_addr.s_addr = inet_addr(ip);
	return si;
}

sockaddr_in forward_util::get_sockaddr_in(__u32 ip, unsigned short port){
	struct sockaddr_in si;
	si.sin_family = PF_INET;
	si.sin_port = htons(port);
	si.sin_addr.s_addr = ip;
	return si;
}

string forward_util::get_addr_by_sockaddr_in(sockaddr_in& si){
	struct in_addr ia;
	ia.s_addr = si.sin_addr.s_addr;
	string ip = inet_ntoa(ia);
	return ip;
}

unsigned short forward_util::get_port_by_sockaddr_in(sockaddr_in& si){
	return ntohs(si.sin_port);
}

unsigned int forward_util::get_uid_by_net_src_port(const char* file_path, unsigned short port){

	struct timeval begin, end;
	gettimeofday(&begin, NULL);

	
	unsigned int ret = 0;
	FILE * fp;
	size_t len = 0;
	char* read;
	char buffer[1024] = {0};

	if (file_path == NULL){
		return ret;
	}

	fp = fopen(file_path, "r");
	if (fp == NULL) {
		return ret;
	}

	int line_cnt = 0;
	while ((read = fgets(buffer, sizeof(buffer)-1, fp)) != NULL) {
		line_cnt++;
		if (line_cnt == 1){
			continue;
		}

		//LOGI("%s", buffer);

		int last_pos = 0;
		string line = buffer;
		vector<string> vec_line;
		string_util::str_tok(line.c_str(), ' ', vec_line);
		if (vec_line.size() < 8){
			continue;
		}
		//LOGI("------------>src = %s dst = %s \n", vec_line[1].c_str(), vec_line[2].c_str());

		string& src = vec_line[1];
		vector<string> vec_src;
		string_util::str_tok(src, ':', vec_src);
		if (vec_src.size() < 2){
			continue;
		}
		string& src_port = vec_src[1];
		string& uid = vec_line[7];
		//LOGI("------------>src port = %s, uid = %s\n", src_port.c_str(),  uid.c_str());


		bool success = true;
		char*endptr = NULL;
		long val = strtol(src_port.c_str(), &endptr, 16);
		if ((errno == ERANGE && (val == LONG_MAX || val == LONG_MIN)) || (errno != 0 && val == 0)) {
			success = false;
		}
		if (endptr == src_port.c_str()) {
			success = false;
		}
		if (success){
			if (port == val){
				ret = atoi(uid.c_str());
				break;
			}
		}
	}

	if (fp){
		fclose(fp);
	}

	gettimeofday(&end, NULL);
	LOGI("get_uid_by_net_src_port port = %u, ret= %d, interval = %lu us", port , ret, end.tv_usec - begin.tv_usec);

	return ret;
}

unsigned int forward_util::get_uid_by_tcp_src_port(unsigned short port){
	unsigned int uid = 0;
	uid = get_uid_by_tcp4_src_port(port);
	if (!uid){
		uid = get_uid_by_tcp6_src_port(port);
	}
	return uid;
}

unsigned int forward_util::get_uid_by_tcp4_src_port(unsigned short port){
	get_uid_by_net_src_port("/proc/net/tcp", port);
}

unsigned int forward_util::get_uid_by_tcp6_src_port(unsigned short port){
	get_uid_by_net_src_port("/proc/net/tcp6", port);
}

unsigned int forward_util::get_uid_by_udp_src_port(unsigned short port){
	unsigned int uid = 0;
	uid = get_uid_by_udp4_src_port(port);
	if (!uid){
		uid = get_uid_by_udp6_src_port(port);
	}

	return uid;
}

unsigned int forward_util::get_uid_by_udp4_src_port(unsigned short port){
	get_uid_by_net_src_port("/proc/net/udp", port);
}

unsigned int forward_util::get_uid_by_udp6_src_port(unsigned short port){
	get_uid_by_net_src_port("/proc/net/udp6", port);
}


